package cz.muni.fi.pa165.travelagency.persistence;

import cz.muni.fi.pa165.travelagency.api.entities.ITour;
import cz.muni.fi.pa165.travelagency.entities.Order;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 * Implementation of OrderDAO interface
 *
 * @author Marián Mozola
 * @version 1.0
 */
@Stateless
public class OrderDAO implements IOrderDAO {

    @PersistenceContext(unitName = "LivePU")
    private EntityManager em;

    public void setEntityManager(EntityManager em) {
        if (em == null) {
            throw new IllegalArgumentException("EntityManager is null.");
        }

        this.em = em;
    }

    @Override
    public void createOrder(Order order) {
        if (order == null) {
            throw new IllegalArgumentException("Argument order cannot be null.");
        }
        if (order.getId() != null) {
            throw new IllegalStateException("Id of the order is incorrect.");
        }
        if (order.getCreated() == null || order.getCreated().compareTo(new Date(System.currentTimeMillis())) > 0) {
            throw new IllegalStateException("Created date of order is incorrect.");
        }
        if (order.getCustomer() == null) {
            throw new IllegalStateException("Customer couldn't be load.");
        }
        if (order.getNumberOfPersons() < 1) {
            throw new IllegalStateException("Number of persons cannot be lesser than 1.");
        }
        if (order.getOrderedPackageTour() == null) {
            throw new IllegalStateException("Package tour is invalid.");
        }
        if (order.getPrice() == null) {
            throw new IllegalStateException("Price cannot be null.");
        }
        if (order.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalStateException("Price cannot be negative number or zero.");
        }

        try {
            em.persist(order);
        } catch (Exception e) {
            Logger.getLogger(OrderDAO.class.getName()).log(Level.SEVERE, e.getMessage(), e);
            throw new DAOException(e.getMessage(), e);
        }
    }

    @Override
    public void deleteOrder(Order order) {
        if (order == null) {
            throw new IllegalArgumentException("Argument order cannot be null.");
        }
        if (order.getId() == null || order.getId() <= 0) {
            throw new IllegalArgumentException("Id of the order is incorrect.");
        }

        try {
            order = em.merge(order);
            List<ITour> tours = order.getOrderedTours();
            for (ITour t : tours) {
                t.getOrders().remove(order);
                em.merge(t);
            }
            em.remove(order);
        } catch (Exception e) {
            Logger.getLogger(OrderDAO.class.getName()).log(Level.SEVERE, e.getMessage(), e);
            throw new DAOException(e.getMessage(), e);
        }
    }

    @Override
    public List<Order> findAll() {
        Query query = em.createQuery("SELECT order FROM Order order");
        List<Order> result = query.getResultList();

        return result;
    }

    @Override
    public List<Order> findUnpaid() {
        Query query = em.createQuery("SELECT order FROM Order order WHERE paid = 'false'");
        List<Order> result = query.getResultList();

        return result;
    }

    @Override
    public Order getOrder(Long id) {
        if (id == null) {
            throw new IllegalArgumentException("Argument id cannot be null.");
        }
        if (id < 0) {
            throw new IllegalArgumentException("Argument id must be greater or equal to 0.");
        }

        Order order = em.find(Order.class, id);

        return order;
    }

    @Override
    public void updateOrder(Order order) {
        if (order == null) {
            throw new IllegalArgumentException("Argument order cannot be null.");
        }
        if (order.getId() == null || order.getId() <= 0) {
            throw new IllegalStateException("Id of the order to update is incorrect.");
        }
        if (order.getCreated() == null || order.getCreated().compareTo(new Date(System.currentTimeMillis())) > 0) {
            throw new IllegalStateException("Created date of order is incorrect.");
        }
        if (order.getCustomer() == null) {
            throw new IllegalStateException("Customer couldn't be load.");
        }
        if (order.getNumberOfPersons() < 1) {
            throw new IllegalStateException("Number of persons cannot be lesser than 1.");
        }
        if (order.getOrderedPackageTour() == null || order.getOrderedTours() == null) {
            throw new IllegalStateException("Ordered tours are invalid.");
        }
        if (order.getPrice() == null) {
            throw new IllegalStateException("Price cannot be null.");
        }
        if (order.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalStateException("Price cannot be negative number or 0.");
        }

        try {
            em.merge(order);
        } catch (Exception e) {
            Logger.getLogger(OrderDAO.class.getName()).log(Level.SEVERE, e.getMessage(), e);
            throw new DAOException(e.getMessage(), e);
        }
    }
}
